///*
// * To change this template, choose Tools | Templates
// * and open the template in the editor.
// */
//package neuralmusic.brain;
//
//import java.util.Collection;
//import java.util.LinkedList;
//import java.util.Queue;
//import java.util.concurrent.Delayed;
//import java.util.concurrent.TimeUnit;
//
//import uk.co.drpj.util.tweaks.Tweakable;
//
///**
// *
// * @author pjl
// */
//public class TrainableNeuron implements Delayed,ConnectionSink,Location  {
//
//    static long count = 0;
//    static boolean debug = false;
//    // external
//    private final Queue<TrainableNeuron> fireQueue;
//    long id;
//    Collection<Connection> out;
// //   TimeRef ref;
//    double lastUpdateTime;
//    double state;
//    double trainState;
//    float alpha;
//    float thresh;
//    final Tweakable threshMod;
//    private float outputVal;
//  
//    boolean firing = false;
//    private long trigger;   // time we want to fire
//    private long delay;     // delay from current time for firing
//    final Point pt; 
//    private Tweakable learning;
//    private final NeuronParams param;
//    
//    /**
//     *
//     * @param ref         time reference
//     * @param pt          point in space (GUI)
//     * @param fireQue     queue to go on fo firing
//     * @param thresh      threshold for firing
//     * @param outputVal   value when firing
//     *
//     * @param timeConstant      decay    e^{ -timeConstant*time )
//     */
//    TrainableNeuron(Point pt, Queue<TrainableNeuron> fireQue, NeuronParams pram,Tweakable threshMod,Tweakable learning) {
//        this.threshMod=threshMod;
//       
//        this.pt = pt;
//        this.out = new LinkedList<Connection>();
//        this.fireQueue = fireQue;
//        this.thresh = pram.thresh;
//        this.id = count++;
//        this.outputVal = pram.outputVal;
//        this.param=pram;
//        this.delay = pram.delay;
//        this.learning=learning;
//        this.state=0;
//        //       in = new LinkedList<Connection>();
//    }
//
//    // apply any pending decay due to time lasped to the state.
//    public void updateState() {
//        double now = TimeRef.getCurrentTimeInMillis();
//        state = state * Math.exp(-param.timeConstant * (now - lastUpdateTime));
//        trainState = trainState * Math.exp(-param.timeConstant * (now - lastUpdateTime));
//        lastUpdateTime = now;
//    }
//
//
//    public void train(float val) {
//        updateState();
//        trainState +=val;
//    }
//
//    @Override
//    public void excite(Connection con,float val) {
//
//        updateState();
//
//        state += val;
//
//        if (debug) {
//            System.out.println("val,state,thresh=" + val + " " + state + " " + thresh*threshMod.doubleValue());
//        }
//
////        if (con!= null && learning != null && learning.isOn() ) {
////            con.reenforce((float) trainState-0.5f);
////        }
//
//        if (firing) {
//            return;
//        }
//
//        if (state > thresh*threshMod.doubleValue()) {
//            if (debug) {
//                System.out.println("queue: " + this);
//            }
//            trigger = TimeRef.getCurrentTimeInMillis() + delay;
//            fireQueue.add(this);
//            firing = true;
//        }
//
//    }
//
//    void fire() {
//
//        if (debug) {
//            System.out.println("fire: " + this);
//        }
//        for (Connection c : out) {
//            c.fire(outputVal, lastUpdateTime);
//        }
//
//        state -= thresh*threshMod.doubleValue();
//        firing = false;
//
//        // see if we still have enouigh juice to refire
//
//        excite(null,0);
//    }
//
//    /**
//     *
//     * @return normalized state (for the GUI)
//     */
//    public float getDisplayValue() {
//        updateState();
//        return (float) (state / (thresh * threshMod.doubleValue()));
//    }
//
//    @Override
//    public Point getPoint() {
//        return pt;
//    }
//
//    void addOut(Connection c) {
//        out.add(c);
//    }
//
//    @Override
//    public String toString() {
//        return Long.toString(id);
//    }
//
//    @Override
//    public long getDelay(TimeUnit unit) {
//        long n = trigger - TimeRef.getCurrentTimeInMillis();
//        return unit.convert(n, TimeRef.timeUnit);
//
//    }
//
//    @Override
//    public int compareTo(Delayed o) {
//        long i = trigger;
//        long j = ((TrainableNeuron) o).trigger;
//        if (i < j) {
//            return -1;
//        }
//        if (i > j) {
//            return 1;
//        }
//        return 0;
//    }
//}
